package com.xy.netty.dome.echo.original;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

/**
 * @author 1
 */
@Slf4j
public class BioServer {
    private static final ThreadLocal<Socket> currentSocket = new ThreadLocal<>();
    private static final int PORT = 8080;
    public static void main(String[] args)throws IOException {
        ServerSocket server = null;
        try {
            server = new ServerSocket(PORT);
            log.info("the time server is start in port :"+PORT);
            Socket socket = null;
            int workConnections = 40960;//工作连接数
            int corePoolSize=Runtime.getRuntime().availableProcessors();
            int maximumPoolSize= BigDecimal
                    .valueOf(corePoolSize)
                    .multiply(BigDecimal.valueOf(0.8))
                    .multiply(BigDecimal.valueOf(workConnections))
                                    .intValue();
            int keepAliveTime = 20;//时间单位秒
            BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(1);
            ExecutorService threadPoolExecutor = new ThreadPoolExecutor(
                    corePoolSize,//当workQueue队列中的元素还未到达最大值时，corePoolSize表示的池中线程数量的最大值；
                    maximumPoolSize,//线程池中允许的最大线程数
                    keepAliveTime,//当前池中的线程数如果超过了corePoolSize，那么超出那些线程如果空闲太久了，应该需要销毁的。keepAliveTime就是的是这些线程的最大空闲时间；
                    TimeUnit.SECONDS,//keepAliveTime的时间单位
                    blockingQueue,//当池中线程数的数量已经达到了corePoolSize，那么如果请求还继续过来，会把请求对应的task放入队列中；
                    new RefuseHandler()//当workQueue满了，池中的线程数又达到了maximumPoolSize，这个时候已经没有多余的资源处理请求了，需要RejectedExecutionHandler 来处理。拒绝处理或者丢弃任务等等。
            );
            //            执行过程
            //            当没有请求时，线程池中没有任何线程；
            //            当有请求时，创建线程，一直到池中的线程数等于corePoolSize；
            //            如果请求太多，需要更多的线程来处理的话，ThreadPoolExecutor选择把请求放入队列中，暂时不新建线程；
            //            如果workQueue也满了，ThreadPoolExecutor会继续创建线程，直到线程数量跟maximumPoolSize相等；
            while (true){
                //堵塞等待客户端发送消息
                socket  =  server.accept();
                currentSocket.set(socket);
                threadPoolExecutor.submit(new TimeServerHandler(socket));
                //new Thread(new TimeServerHandler(socket)).start();
            }
        }catch (Exception e){
            log.error("ServerSocket错误",e);
        }finally {
            if(server != null){
                log.info("the time server close");
                server.close();
            }
            if(currentSocket.get() != null){
                currentSocket.remove();
            }
        }


    }

    public static ThreadLocal<Socket> getCurrentSocket() {
        return currentSocket;
    }
}
